package cn.numeron.common.utility

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.*
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStoreFile
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import java.util.*

object Preferences {

    private const val FILE_NAME = "common"

    lateinit var dataStore: DataStore<Preferences>
        private set

    fun init(context: Context) {
        dataStore = PreferenceDataStoreFactory.create {
            context.applicationContext.preferencesDataStoreFile(FILE_NAME)
        }
    }

    suspend inline fun edit(noinline transform: suspend (MutablePreferences) -> Unit) =
        dataStore.edit(transform)

    suspend inline fun update(noinline transform: suspend (Preferences) -> Unit) =
        dataStore.updateData {
            it.apply {
                transform(this)
            }
        }

    @Suppress("UNCHECKED_CAST", "CAST_NEVER_SUCCEEDS")
    fun <T> getPrefAsFLow(key: String, default: T): Flow<T> {
        val prefKey = when (default) {
            is Int -> intPreferencesKey(key)
            is Float -> floatPreferencesKey(key)
            is Double -> doublePreferencesKey(key)
            is String -> stringPreferencesKey(key)
            is Boolean -> booleanPreferencesKey(key)
            is Long, is Date -> longPreferencesKey(key)
            else -> throw UnsupportedOperationException()
        }
        val valueClass = default.javaClass
        return dataStore.data.map {
            val prefValue = it[prefKey]
            if (default is Date) {
                Date(prefValue as Long) as T
            } else {
                valueClass.cast(prefValue)!!
            }
        }
    }

}